#ifndef __GUI_H__
#define __GUI_H__

#ifdef CLE_NAMESPACE
namespace gui {
#endif

#ifdef _DEBUG
#define __TEST_DEBUG__
#endif

#ifdef _MSC_VER
#pragma warning(disable: 4786)
#endif

#ifdef __TEST_DEBUG__
#include <stdio.h>
#define dprint                         printf
#  ifdef UNICODE
#    define dgprint                    wprintf
#  else
#    define dgprint                    printf
#  endif
#else
#define dprint                         //
#define dgprint                        //
#endif

#ifdef __TEST_DEBUG__
#include <time.h>
#define TEST_SEGMENT_START()         clock_t __st__ = clock()
#define TEST_SEGMENT_END(str)        dprint("#### "#str"Time:%6dms\n", clock() - __st__)
#define TEST_FUNC(func)              do { TEST_SEGMENT_START(); func ; TEST_SEGMENT_END(func); }while (0)
#else
#define TEST_SEGMENT_START()         //
#define TEST_SEGMENT_END(str)        //
#define TEST_FUNC(func)              func
#endif

#include <string>  // for std::wstring
#include <map>
#include <vector>

typedef unsigned char             uchar;
typedef unsigned short            ushort;
typedef unsigned int              uint;
typedef unsigned long             ulong;

typedef void*                     GHForm;
typedef void*                     GHMenu;

#ifdef UNICODE
typedef wchar_t                   gchar;
typedef std::wstring              GString;
#define GTEXT(q)                  L##q
#else
typedef char                      gchar;
typedef std::string               GString;
#define GTEXT(q)                  q
#endif

enum  TextEncoding { Unicode = 0, UTF_8, UTF_16 };


class GPoint
{
public:
    int x, y;

    GPoint(int p = 0)
        :x(p),y(p){}
    GPoint(int _x, int _y)
        :x(_x), y(_y) {}

	bool operator == (const GPoint&pt )const { return (x == pt.x)&&(y == pt.y); }
};

class GSize
{
public:
    int w, h;
    
    GSize(int s = 0)
        :w(s),h(s){}
    GSize(int _w, int _h)
        :w(_w), h(_h) {}

    bool operator == (const GSize& sz )const { return (w == sz.w)&&(h == sz.h); }
};

class GRect
{
public:
    int left, top, right,bottom;

    GRect(int x, int y, int w, int h)
        :left(x), top(y), right(x+w-1), bottom(y+h-1) {}
    GRect()
        :left(0), top(0),right(0),bottom(0) {}
    int                 width() const { return right - left + 1; }
    int                 height() const { return bottom - top + 1; }
	void                setWidth(int w) { right = left + w - 1;}
	void                setHeight(int h) { bottom = top + h - 1; }
    bool                isValid() const { return width() > 1 && height() > 1; }

    void                adjust(int dl, int dt, int dr, int db){
        left+=dl; top+=dt; right += dr; bottom += db;
    }
    void                translate(int dx, int dy){
        left += dx; right += dx;
		top += dy; bottom += dy;
    }
    bool                contains(const GPoint& pt){ return (pt.x >= left) && (pt.x <= right) && (pt.y >= top) && (pt.y <= bottom); }
    GPoint              center() const { return GPoint((left + right) / 2, (top + bottom) / 2); }
    void                setCenter(const GPoint& point) {
        int w = width(); int h = height();
        left = point.x - w / 2 ; right = left + w - 1;
        top = point.y - h / 2 ; bottom = top + h - 1;
    }
};

class GCursor
{
public:
	enum CursorShape { Arrow, Text, Up, Wait, Horiz, Vert, ReverseArrow, Hand, Default};

	GCursor(CursorShape s)
		:m_shape(s) {}
	void setShape(CursorShape s) { m_shape = s; }
	CursorShape shape()const {return m_shape; }

private:
	CursorShape    m_shape;
};

class GMenu  //implement in platform
{
public:
	GMenu(GHMenu hMenu = 0);
    GHMenu              getHandle()const { return m_hMenu; }

    bool                addItem(uint id, const GString& text);
    bool                addSeparator();
    bool                insertItem(uint index, uint id, const GString& text);
    bool                addMenu(const GMenu& menu);
    bool                insertMenu(uint index, const GMenu& menu);
    GMenu               getSubHandle(int index = 0);
    void                setTitle(const GString& str) { m_szTitle = str;}
    GString             getTitle()const { return m_szTitle;}
    bool                setCheck(int itemID, bool check = true);
    static bool         destroy( GMenu& menu);  

private:
	GHMenu              m_hMenu;
	GString             m_szTitle;
};


#ifdef CLE_NAMESPACE
}
#endif

#endif